<template>
  <PageWrapper
    dense
    :contentClass="getIsMobile?'flow-root px-16px pt-16px':'flex px-16px pt-16px'"
    class="min-h-full rounded-md"
  >
    <template v-if="!config.formTable">
      <AnnoTableTree
        v-if="config?.annoLeftTree?.enable || config?.annoTree?.displayAsTree"
        :left-tree-name="config.annoLeftTree?.enable ? config.annoLeftTree?.leftTreeName : config.name"
        :left-tree-cat-key="
        config.annoLeftTree?.enable ? config.annoLeftTree?.catKey : config.annoTree?.key
      "
        :left-tree-class="
        config.annoLeftTree?.enable ? config.annoLeftTree.treeClass : config.entityName
      "
        :class="getIsMobile ? 'w-full xl:w-1/5 b-r-1 b-r-#eee h-64' : 'w-1/4 xl:w-1/5 b-r-1 b-r-#eee min-h-86svh max-h-100svh'"
        @select="handleSelect"
      />
      <BasicTable
        @register="registerTable"
        :class="
        (config.annoLeftTree?.enable || config.annoTree?.displayAsTree) && !getIsMobile
          ? 'w-3/4 xl:w-4/5'
          : 'w-4/4 xl:w-5/5'
      "
        :searchInfo="searchInfo"
      >
        <template #toolbar>
          <a-button v-for="item in config.tableButtons" type="primary" @click="handleTableClick(item)"
          >{{ item.name }}
          </a-button>
          <a-button
            type="primary"
            @click="handleCreate"
            v-show="(AnnoFormSchema.addScheme || []).length > 0"
          >新增{{ config.name }}
          </a-button>
        </template>
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'action'">
            <TableAction
              :divider="false"
              :actions="getActions(record)"
              :dropDownActions="getMoreActions(record, 'more')"
            />
          </template>
        </template>
      </BasicTable>
    </template>
    <template v-if="config.formTable">
        <FormWithTabs
          :api="api"
          :title="config.name"
          :rowKey="rowKey"
          @success="handleSuccess"
          :table-buttons="config.tableButtons"
          :column-buttons="config.columnButtons"
          :handle-table-click="handleTableClick"
          :handle-column-click="columnBtnClick"
          :edit-schemas="AnnoFormSchema.editScheme || []"
          :add-schemas="AnnoFormSchema.addScheme || []"/>
    </template>

    <AnnoModal
      @register="registerModal"
      :column-m2m-button="
        (config.columnButtons || []).filter((cmb: ColumnButton) => cmb.m2mJoinButton.enable)
      "
      :add-schema="AnnoFormSchema.addScheme || []"
      :edit-schema="AnnoFormSchema.editScheme || []"
      :row-key="rowKey"
      @success="handleSuccess"
    />
    <AnnoM2mModal @register="registerM2mModal" />
    <IFrameModal @register="registerIFrameModal" />
    <DescriptionModal @register="registerDescriptionModal" />
    <ButtonModal @register="registerButtonModal" @success="handleBtnSuccess" />
  </PageWrapper>
</template>
<script lang="ts" setup>
  /* eslint-disable prettier/prettier */
  import {
    deleteData,
    getEntity,
    getTableData,
    runJavaCmd,
    saveData,
    updateData,
  } from '@/api/sys/anno';
  import { reactive } from 'vue';
  import { BasicTable, FormSchema, TableAction, useTable } from '@/components/Table';
  import { PageWrapper } from '@/components/Page';
  import AnnoTableTree from './AnnoTableTree.vue';
  import { AnEntity, ColumnButton } from '@/api/sys/model/entitysModel';
  import { useModal } from '@/components/Modal';
  import AnnoModal from './AnnoModal.vue';
  import ButtonModal from './ButtonModal.vue';
  import AnnoM2mModal from '@/components/AnnoM2m/AnnoM2mModal.vue';
  import IFrameModal from '@/components/IFrameModal/index.vue';
  import {
    getAnnoAddForm,
    getAnnoDescriptionForm,
    getAnnoEditForm,
    getAnnoSearchForm,
    getColumns,
  } from '@/utils/anno';
  import { useMessage } from '@/hooks/web/useMessage';
  import { useGlobSetting } from '@/hooks/setting';
  import querystring from 'qs';
  import { getToken } from '@/utils/auth';
  import DescriptionModal from '@/components/DescriptionModal/index.vue';
  import { DescItem } from '@/components/Description';
  import { useComputed } from '@/utils/anno/useComputed.js';
  import { useAppInject } from '@/hooks/web/useAppInject';
  import FormWithTabs from "./FormWithTabs.vue";

  const { createMessage } = useMessage();
  const route = useRoute();
  const props = defineProps<{
    entityName: string;
  }>();
  let clazz = route.name as string;
  if (route.name == 'BasicPreview') {
    clazz = props.entityName as string;
  }
  const { apiUrl } = useGlobSetting();
  const config = reactive<Partial<AnEntity>>({
    enableLeftTree: false,
  });

  const [registerModal, { openModal }] = useModal();
  const [registerM2mModal, { openModal: openM2modal }] = useModal();
  const [registerButtonModal, { openModal: openButtonModal }] = useModal();
  const [registerIFrameModal, { openModal: openIFrameModal }] = useModal();
  const [registerDescriptionModal, { openModal: openDescriptionModal }] = useModal();
  const searchInfo = reactive<Recordable>({});
  const [registerTable, { reload, setProps, getForm, getSelectRows }] = useTable({});
  const { getIsMobile } = useAppInject();
  const AnnoFormSchema = reactive<Record<string, FormSchema[]>>({
    addScheme: [],
    editScheme: [],
  });
  const descriptionSchema = ref<Array<DescItem>>([] as DescItem[]);
  const api = ref();
  let getActions = (record): any => {
    return [];
  };
  let getMoreActions = (record): any => {
    return [];
  };
  const rowKey = ref('id');
  getEntity(clazz).then((res) => {
    api.value = getTableData(
      res.entityName!,
      res.annoTree.parentKey,
      res.annoTree.key,
      res.annoTree.displayAsTree,
    );
    const searchFormFields = getAnnoSearchForm(res.columns, getIsMobile);
    AnnoFormSchema.addScheme = getAnnoAddForm(res.columns);
    AnnoFormSchema.editScheme = getAnnoEditForm(res.columns);
    descriptionSchema.value = getAnnoDescriptionForm(res.columns);
    rowKey.value = res.pkColumn.javaName;
    let commonCnt = (AnnoFormSchema.editScheme.length > 0 ? 1 : 0) + (res.canRemove ? 1 : 0) + 1;
    let remaining = getIsMobile.value ? 1 - commonCnt : 5 - commonCnt;
    getActions = useComputed((record) => {
      let moreActionsOut = res.columnButtons.slice(0, remaining).map((item) => {
        return {
          icon: item.icon,
          tooltip: item.name,
          onClick: columnBtnClick.bind(null, { props: record, option: item }),
        };
      });
      return [
        {
          icon: 'clarity:info-standard-line',
          tooltip: '查看详情',
          onClick: handleView.bind(null, record),
        },
        {
          icon: 'clarity:note-edit-line',
          tooltip: '编辑资料',
          onClick: handleEdit.bind(null, record),
          ifShow: (_action) => {
            return AnnoFormSchema.editScheme.length > 0; // 根据业务控制是否显示: 非enable状态的不显示启用按钮
          },
        },
        {
          icon: 'ant-design:delete-outlined',
          color: 'error',
          tooltip: '删除此项',
          popConfirm: {
            title: '是否确认删除',
            placement: 'left',
            confirm: handleDelete.bind(null, record),
          },
          ifShow: (_action) => {
            return res.canRemove;
          },
        },
        ...moreActionsOut,
      ];
    });

    getMoreActions = useComputed((record) => {
      if (res.columnButtons.length < remaining) {
        return [];
      }
      return res.columnButtons.slice(remaining).map((item) => {
        return {
          label: item.name,
          tooltip: item.name,
          onClick: columnBtnClick.bind(null, { props: record, option: item }),
        };
      });
    });
    Object.assign(config, res);
    // noinspection TypeScriptValidateTypes
    setProps({
      pagination: {
        pageSize: 10,
      },
      title: config.name,
      api,
      rowSelection: {},
      showIndexColumn: !getIsMobile.value,
      canResize: !getIsMobile.value,
      resizeHeightOffset: 10,
      rowKey: res.pkColumn.javaName,
      columns: getColumns(res.columns),
      indexColumnProps: {
        fixed: 'left',
        width: 50,
      },
      formConfig: {
        rowProps: { gutter: 16, justify: 'start' },
        labelWidth: 100,
        labelAlign: 'left',
        schemas: searchFormFields,
        autoSubmitOnEnter: true,
        autoAdvancedLine: 50,
        showAdvancedButton: false,
        showSubmitButton:
          (searchFormFields || []).filter((item) => item.show({ model: {} })).length > 0,
        showResetButton:
          (searchFormFields || []).filter((item) => item.show({ model: {} })).length > 0,
      },
      useSearchForm: searchFormFields.length > 0,
      showTableSetting: true,
      bordered: true,
      beforeFetch(params) {
        if (!params.anOrderList || params.anOrderList.length === 0) {
          params.anOrderList = res.annoOrder;
        }
        return params;
      },
      actionColumn: {
        width: getIsMobile.value
          ? 65
          : (searchFormFields.length > 0 ? 130 : 100) + (res.columnButtons.length > 0 ? 60 : 0),
        title: '操作',
        dataIndex: 'action',
        // slots: { customRender: 'action' },
      },
    });
    nextTick(() => {
      const form = getForm();
      form.setFieldsValue(route.query);
      form.submit();
    });
  });

  function handleCreate() {
    openModal(true, {
      isUpdate: false,
    });
  }

  const router = useRouter();

  function columnBtnClick({ props, option }) {
    let columnOption = option as ColumnButton;
    let entityName = columnOption.baseForm;
    getEntity(entityName).then((res) => {
      let entity = res;
      if (entity) {
        let columnDataIds = [props[rowKey.value]];
        openButtonModal(true, {
          title: option.name,
          formSchema: getAnnoAddForm(entity.columns),
          parentOptions: option,
          parentProps: props,
          columnDataIds: columnDataIds,
          entityName: entityName,
        });
      } else {
        handleBtnSuccess({
          values: {},
          closeModal: () => {},
          parentOptions: option,
          parentProps: props,
        });
      }
    });
  }

  async function handleBtnSuccess({ values, closeModal, parentOptions, parentProps }) {
    let columnParentOptions = parentOptions as ColumnButton;
    let props = parentProps;
    if (columnParentOptions.javaCmd.enable) {
      runJavaCmd(clazz, {
        annoJavaCmdId: columnParentOptions.javaCmd.id,
        _extra: values,
        ...parentProps,
      }).then((res) => {
        let data = res.trimStart();
        if (data) {
          // msg 以 js:// 开头
          if (data.startsWith('js://')) {
            eval(data.substring(5));
          } else if (data.startsWith('iframe://')) {
            openIFrameModal(true, {
              modalTitle: `${columnParentOptions.name}`,
              fullScreen: false,
              modalWidth: 900,
              modalHeight: 500,
              iframeSrc: `${data.substring(9)}&_t=${Date.now()}`,
            });
          } else if(data.startsWith('iframeDoc://')) {
            openIFrameModal(true, {
              modalTitle: `${columnParentOptions.name}`,
              fullScreen: false,
              modalWidth: 900,
              modalHeight: 500,
              iframeSrcDoc: data.substring(12),
            });
          }else {
            createMessage.success(data);
          }
        } else {
          createMessage.success('操作成功');
        }
        reload();
        closeModal();
      });
    }
    if (columnParentOptions.jumpUrl) {
      columnParentOptions.jumpUrl = columnParentOptions.jumpUrl.replace(
        '${props}',
        JSON.stringify(parentProps),
      );
      closeModal();
      window.open(columnParentOptions.jumpUrl);
    }
    if (columnParentOptions.jsCmd) {
      eval(columnParentOptions.jsCmd);
      closeModal();
    }
    if (columnParentOptions.m2mJoinButton.enable) {
      openM2modal(true, {
        props: parentProps,
        option: columnParentOptions,
        isAdd: false,
      });
      closeModal();
    }
    if (columnParentOptions.o2mJoinButton.enable) {
      const query = {};
      query[columnParentOptions.o2mJoinButton.targetJavaField] =
        parentProps[columnParentOptions.o2mJoinButton.thisJavaField];
      closeModal();
      await router.push({ name: columnParentOptions.o2mJoinButton.targetClass, query });
    }
    if (columnParentOptions.annoTpl.enable) {
      openIFrameModal(true, {
        modalTitle: columnParentOptions.name,
        modalWidth: columnParentOptions.annoTpl.windowWidth,
        modalHeight: columnParentOptions.annoTpl.windowHeight,
        iframeSrc: `${apiUrl}/anno-admin-api/annoTpl?_tplId=${
          columnParentOptions.annoTpl.id
        }&${querystring.stringify(parentProps)}&_tokenValue=${getToken()}`,
      });
      closeModal();
    }
  }

  function handleEdit(record: Recordable) {
    console.log('edit', record);
    openModal(true, {
      record,
      isUpdate: true,
    });
  }

  function handleDelete(record: Recordable) {
    console.log(record);
    const param = {};
    param[config.pkColumn!.javaName] = record[config.pkColumn!.javaName];
    deleteData(config.thisClass as string, param).then((res) => {
      reload();
    });
  }

  async function handleSuccess({ isUpdate, values, closeModal }) {
    if (isUpdate) {
      if (
        (config.annoTree?.enable || config.annoTree?.displayAsTree) &&
        values[config.annoTree.key] == values[config.annoTree.parentKey]
      ) {
        createMessage.error('不能选择自己为自己的子节点');
        return;
      }
      await updateData(config.thisClass as string, values).then((res) => {
        reload();
        closeModal();
        createMessage.success('更新成功');
      });
    } else {
      await saveData(config.thisClass as string, values).then((res) => {
        console.log(res);
        reload();
        closeModal();
        createMessage.success('保存成功');
      });
    }
  }

  function handleSelect(value = '') {
    searchInfo[config.annoLeftTree?.catKey || config.annoTree?.key || '__'] = value;
    getForm().setFieldsValue(searchInfo);
    getForm().submit();
  }

  function handleView(record: Recordable) {
    openDescriptionModal(true, {
      modalTitle: '详情',
      modalWidth: 900,
      modalHeight: 500,
      rowData: record,
      descriptionSchemaParam: descriptionSchema,
    });
  }

  const handleTableClick = (item: any) => {
    let entityName = item.baseForm;
    let fieldsValue = getForm().getFieldsValue();
    let thisProps = {
      selectRows: getSelectRows(),
      ...fieldsValue,
    };
    getEntity(entityName).then((res) => {
      let entity = res;
      if (entity) {
        openButtonModal(true, {
          title: item.name,
          formSchema: getAnnoAddForm(entity.columns),
          parentOptions: item,
          parentProps: thisProps,
        });
      } else {
        handleBtnSuccess({
          values: {},
          closeModal: () => {},
          parentOptions: item,
          parentProps: thisProps,
        });
      }
    });
  };
</script>
